import { Schema } from './schema';
import { Rule, Tree } from '@angular-devkit/schematics';
import {
  getProjectFromWorkspace,
  getProjectMainFile,
  parseSourceFile,
  insertImport,
  addSymbolToNgModuleMetadata,
} from '@angular/cdk/schematics';
import { InsertChange } from '@schematics/angular/utility/change';
import { getAppModulePath } from '@schematics/angular/utility/ng-ast-utils';
import { getWorkspace } from '@schematics/angular/utility/workspace';

export function updateAppModule(options: Schema): Rule {
  return async (host: Tree) => {
    const workspace = await getWorkspace(host);
    const project = getProjectFromWorkspace(workspace, options.project);
    const appModulePath = getAppModulePath(host, getProjectMainFile(project));
    const moduleSource = parseSourceFile(host, appModulePath);

    const recorder = host.beginUpdate(appModulePath);

    const changes = [
      insertImport(
        moduleSource,
        appModulePath,
        'LayoutModule',
        'joy-abpui-angular'
      ),
      ...addSymbolToNgModuleMetadata(
        moduleSource,
        appModulePath,
        'imports',
        `LayoutModule.forRoot()`,
        null
      ),

      insertImport(
        moduleSource,
        appModulePath,
        'AccountModule',
        'joy-abpui-angular'
      ),
      ...addSymbolToNgModuleMetadata(
        moduleSource,
        appModulePath,
        'imports',
        `AccountModule.forRoot()`,
        null
      ),

      insertImport(
        moduleSource,
        appModulePath,
        'IdentityModule',
        'joy-abpui-angular'
      ),
      ...addSymbolToNgModuleMetadata(
        moduleSource,
        appModulePath,
        'imports',
        `IdentityModule.forRoot()`,
        null
      ),

      insertImport(
        moduleSource,
        appModulePath,
        'SettingManagementModule',
        'joy-abpui-angular'
      ),
      ...addSymbolToNgModuleMetadata(
        moduleSource,
        appModulePath,
        'imports',
        `SettingManagementModule.forRoot()`,
        null
      ),

      insertImport(
        moduleSource,
        appModulePath,
        'TenantManagementModule',
        'joy-abpui-angular'
      ),
      ...addSymbolToNgModuleMetadata(
        moduleSource,
        appModulePath,
        'imports',
        `TenantManagementModule.forRoot()`,
        null
      ),

      insertImport(
        moduleSource,
        appModulePath,
        'MessageModule',
        'joy-abpui-angular'
      ),
      ...addSymbolToNgModuleMetadata(
        moduleSource,
        appModulePath,
        'imports',
        `MessageModule.forRoot()`,
        null
      ),

      insertImport(
        moduleSource,
        appModulePath,
        'RouteReuseStrategy',
        '@angular/router'
      ),
      insertImport(
        moduleSource,
        appModulePath,
        'RouteTabReuseStrategy',
        'joy-abpui-angular'
      ),
      ...addSymbolToNgModuleMetadata(
        moduleSource,
        appModulePath,
        'providers',
        `{ provide: RouteReuseStrategy, useClass: RouteTabReuseStrategy }`,
        null
      ),

      insertImport(moduleSource, appModulePath, 'NgxsModule', '@ngxs/store'),
      ...addSymbolToNgModuleMetadata(
        moduleSource,
        appModulePath,
        'imports',
        `NgxsModule.forRoot([], { developmentMode: !environment.production })`,
        null
      ),

      insertImport(
        moduleSource,
        appModulePath,
        'LocationStrategy',
        '@angular/common'
      ),
      insertImport(
        moduleSource,
        appModulePath,
        'HashLocationStrategy',
        '@angular/common'
      ),
      ...addSymbolToNgModuleMetadata(
        moduleSource,
        appModulePath,
        'providers',
        `{ provide: LocationStrategy, useClass: HashLocationStrategy }`,
        null
      ),
    ];

    changes.forEach((change) => {
      if (change instanceof InsertChange) {
        recorder.insertLeft(change.pos, change.toAdd);
      }
    });

    host.commitUpdate(recorder);

    return;
  };
}
